
/**
 * https://javadoop.com/post/java-thread-pool
 *
 *
 * Executor  最顶层接口
 * ExecutorService 也是接口，在 Executor 接口的基础上添加了很多的接口方法，所以一般来说我们会使用这个接口。
 * Executors 是工具类，
 * 定时任务实现类 ScheduledThreadPoolExecutor，它继承自本文要重点讲解的 ThreadPoolExecutor，用于实现定时执行。
 *
 * FutureTask
 *
 *  Future      Runnable
 *    \           /
 *     \         /
 *    RunnableFuture
 *           |
 *           |
 *       FutureTask
 *
 * FutureTask 通过 RunnableFuture 间接实现了 Runnable 接口，
 * 所以每个 Runnable 通常都先包装成 FutureTask，
 * 然后调用 executor.execute(Runnable command) 将其提交给线程池
 *
 *
 * ExecutorCompletionService
 * ExecutorCompletionService 不是一个真正的执行器，参数 this 才是真正的执行器
 * 它对执行器进行了包装，每个任务结束后，将结果保存到内部的一个 completionQueue 队列中
 *
 * ThreadPoolExecutor
 *  1. Doug Lea 采用一个 32 位的整数来存放线程池的状态和当前池中的线程数，
 *
 *     其中高 3 位用于存放线程池状态，低 29 位表示线程数（即使只有 29 位，也已经不小了，大概 5 亿多，现在还没有哪个机器能起这么多线程的吧）。
 *
 *       RUNNING 定义为 -1，SHUTDOWN 定义为 0，其他的都比 0 大，所以等于 0 的时候不能提交任务，大于 0 的话，连正在执行的任务也需要中断。
 *
 *       RUNNING：这个没什么好说的，这是最正常的状态：接受新的任务，处理等待队列中的任务
 *       SHUTDOWN：不接受新的任务提交，但是会继续处理等待队列中的任务
 *       STOP：不接受新的任务提交，不再处理等待队列中的任务，中断正在执行任务的线程
 *       TIDYING：所有的任务都销毁了，workCount 为 0。线程池的状态在转换为 TIDYING 状态时，会执行钩子方法 terminated()
 *       TERMINATED：terminated() 方法结束后，线程池的状态就会变成这个
 *
 *      RUNNING -> SHUTDOWN：当调用了 shutdown() 后，会发生这个状态转换，这也是最重要的
 *      (RUNNING or SHUTDOWN) -> STOP：当调用 shutdownNow() 后，会发生这个状态转换，这下要清楚 shutDown() 和 shutDownNow() 的区别了
 *      SHUTDOWN -> TIDYING：当任务队列和线程池都清空后，会由 SHUTDOWN 转换为 TIDYING
 *      STOP -> TIDYING：当任务队列清空后，发生这个转换
 *      TIDYING -> TERMINATED：这个前面说了，当 terminated() 方法结束后
 *
 *
 *   2. 内部类 Worker，因为 Doug Lea 把线程池中的线程包装成了一个个 Worker，翻译成工人，就是线程池中做任务的线程。
 *      任务是 Runnable（内部变量名叫 task 或 command），线程是 Worker。 run ->  runWorker(this);
 *      Worker 这里又用到了抽象类 AbstractQueuedSynchronizer

 *
 *   3. corePoolSize，maximumPoolSize，workQueue，keepAliveTime，rejectedExecutionHandler
 *      corePoolSize 到 maximumPoolSize 之间的线程会被回收，当然 corePoolSize 的线程也可以通过设置而得到回收（allowCoreThreadTimeOut(true)）。
 *      workQueue 用于存放任务，添加任务的时候，如果当前线程数超过了 corePoolSize，那么往该队列中插入任务，线程池中的线程会负责到队列中拉取任务。
 *      keepAliveTime 用于设置空闲时间，如果线程数超出了 corePoolSize，并且有些线程的空闲时间超过了这个值，会执行关闭这些线程的操作
 *      rejectedExecutionHandler 用于处理当线程池不能执行此任务时的情况，默认有抛出 RejectedExecutionException 异常、
 *      忽略任务、使用提交任务的线程来执行此任务和将队列中等待最久的任务删除，然后提交此任务这四种策略，默认为抛出异常。
 *

 */
package cn.hy.concurrent.线程池;
